package com.gdc.cloud.controller;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.gdc.cloud.entities.CommonResult;
import com.gdc.cloud.entities.Payment;
import com.gdc.cloud.handler.CustomerBlockHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Description: 流控测试
 * @author: gdc
 * @date: 2022/5/23
 * @version 1.0
 */
@RequestMapping("rateLimit")
@RestController
public class RateLimitController {

    /**
     * 流控规则_根据资源名(byResource)_添加流控规则
     *  当前方法有兜底方案：handleException，当超过流控限制时，展示的是handleException()方法返回的信息
     */
    @GetMapping("/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public CommonResult byResource() {
        return new CommonResult(200, "按照资源名称限流测试 OK", new Payment(2022L, "20220523_1"));
    }

    /**
     * 流控兜底解决方案
     */
    public CommonResult handleException(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
    }


    /**
     * 流控规则_根据请求地址(/rateLimit/byUrl)_添加流控规则
     *  当前方法没有有兜底方案,当超过流控限制时，展示的是Sentinel默认的异常提示
     */
    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl() {
        return new CommonResult(200, "按照Url限流测试 OK", new Payment(2022L, "20220523_2"));
    }

    /**
     * 流控规则_添加统一的流控处理类方法
     * - @SentinelResource
     *  - blockHandlerClass；指定处理类（用于统一定义）
     *  - blockHandler: 该函数访问范围需要是 public，返回类型需要与原方法相匹配，参数类型需要和原方法相匹配并且最后加一个额外的参数，类型为 BlockException。
     *      blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数，则可以指定 blockHandlerClass 为对应的类的 Class 对象，注意对应的函数必需为 static 函数，否则无法解析。
     */
    @GetMapping("/rateLimit/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler",
        blockHandlerClass = CustomerBlockHandler.class,
        blockHandler = "handlerException2")
    public CommonResult customerBlockHandler() {
        return new CommonResult(200, "按照客户自定义测试 OK", new Payment(2022L, "20220523_3"));
    }
}
